package com.flow.framework.module.call.rpc.interceptor;

import com.flow.framework.common.constant.FrameworkCommonConstant;
import com.flow.framework.core.constant.FrameworkCoreConstant;
import com.flow.framework.core.service.properties.ISystemConfigPropertiesService;
import com.flow.framework.core.system.listener.lifecycle.ISystemLifecycleListener;
import com.flow.framework.module.call.constant.FrameworkModuleCallConstant;
import com.flow.framework.module.call.rpc.manager.FeignManager;
import com.flow.framework.module.call.rpc.proto.CustomizationVoid;
import feign.MethodMetadata;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.Target;
import lombok.RequiredArgsConstructor;
import org.slf4j.MDC;
import org.springframework.context.i18n.LocaleContextHolder;

/**
 * 在feign调用时，将traceId、调用者微服务名称、客户端语言环境等通用处理
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/2/19
 */
@RequiredArgsConstructor
public class FeignCommonInterceptor implements RequestInterceptor, ISystemLifecycleListener {

    private final ISystemConfigPropertiesService systemConfigPropertiesService;

    private final FeignManager feignManager;

    private String appName;

    /**
     * @inheritDoc
     */
    @Override
    public void apply(RequestTemplate requestTemplate) {

        // 将代理方法的void返回值替换为自定CustomizationVoid类型
        // 方便在com.flow.framework.rpc.decoder.CustomizationRpcSuccessDecoder中对其他数据进行校验，如响应header中的框架响应
        MethodMetadata methodMetadata = requestTemplate.methodMetadata();
        if (void.class == methodMetadata.returnType()) {
            methodMetadata.returnType(CustomizationVoid.class);
        }

        requestTemplate.removeHeader(FrameworkCommonConstant.GLOBAL_LOG_TRACE_KEY);
        requestTemplate.removeHeader(FrameworkCoreConstant.GLOBAL_PREVIOUS_APP_KEY);
        requestTemplate.removeHeader(FrameworkModuleCallConstant.INNER_REQUEST_KEY);

        Target<?> target = requestTemplate.feignTarget();
        if (!feignManager.isInnerRequest(target)) {
            return;
        }
        requestTemplate.header(FrameworkModuleCallConstant.INNER_REQUEST_KEY, String.valueOf(true));
        requestTemplate.header(FrameworkCommonConstant.GLOBAL_LOG_TRACE_KEY,
                MDC.get(FrameworkCommonConstant.GLOBAL_LOG_TRACE_KEY));
        requestTemplate.header(FrameworkCoreConstant.GLOBAL_PREVIOUS_APP_KEY, appName);
        requestTemplate.header("accept-language", LocaleContextHolder.getLocale().getLanguage());
    }

    @Override
    public void onStartUp() {
        appName = systemConfigPropertiesService.getConfigValue(FrameworkCoreConstant.SERVICE_NAME_KEY, "unknown");
    }
}
